<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Three.js Snowfall Effect with Canvas Snowflake</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script>
    // 初始化Three.js场景
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建立方体
    var geometry = new THREE.BoxGeometry(1, 1, 1);
    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    var cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 添加光源
    var light = new THREE.DirectionalLight(0xffffff);
    light.position.set(1, 1, 1).normalize();
    scene.add(light);

    // 射线摄取器
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    // 鼠标事件监听
    var isDragging = false;
    var offset = new THREE.Vector3();

    document.addEventListener('mousedown', onDocumentMouseDown, false);
    document.addEventListener('mousemove', onDocumentMouseMove, false);
    document.addEventListener('mouseup', onDocumentMouseUp, false);

    function onDocumentMouseDown(event) {
        event.preventDefault();

        isDragging = true;

        var intersects = getIntersects(event.layerX, event.layerY);
        if (intersects.length > 0) {
            var intersect = intersects[0];
            offset.copy(intersect.point).sub(cube.position);
        }
    }

    function onDocumentMouseMove(event) {
        event.preventDefault();

        if (isDragging === true) {
            var intersects = getIntersects(event.layerX, event.layerY);
            if (intersects.length > 0) {
                var intersect = intersects[0];
                cube.position.copy(intersect.point.sub(offset));
            }
        }

        render();
    }

    function onDocumentMouseUp(event) {
        event.preventDefault();

        isDragging = false;
    }

    function getIntersects(x, y) {
        x = (x / window.innerWidth) * 2 - 1;
        y = -(y / window.innerHeight) * 2 + 1;

        mouse.x = x;
        mouse.y = y;

        raycaster.setFromCamera(mouse, camera);

        return raycaster.intersectObject(cube);
    }

    // 渲染函数
    function render() {
        renderer.render(scene, camera);
    }

    // 动画循环
    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    animate();

</script>
</body>
</html>
